package MetroLab.Utils;

import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.objectfile.ObjectFile;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import java.util.Enumeration;
import javax.media.j3d.*;
import javax.media.j3d.TextureAttributes;
import javax.vecmath.Color3f;

/**
 *
 * @author plus
 */
public class ObjectFactory {

    private static java.awt.Panel PanelTexture = new java.awt.Panel();

    public static Group createObject(String Key) {
        Group res = null;
        try {
            res = LoadSimpleObjectFromFile(PathRes.getPath(Key), false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        res.setPickable(false);
        return res;
    }

    public static Group createObject(String Key, boolean reformable) {
        Group res = null;
        try {
            res = LoadSimpleObjectFromFile(PathRes.getPath(Key), reformable);
        } catch (Exception e) {
            e.printStackTrace();
        }
        res.setPickable(false);
        return res;
    }

    public static void LoadTextureToAppearance(Appearance app, String fName) {
        try {
            TextureLoader texLoader = new TextureLoader(fName, PanelTexture);
            app.setTexture(texLoader.getTexture());
        } catch (Exception e) {
            System.out.println("Miss " + fName + "?");
        }
        TextureAttributes texAtt = new TextureAttributes();
        texAtt.setTextureMode(TextureAttributes.MODULATE);
        //texAtt.setCombineRgbMode(texAtt.COMBINE_MODULATE);
        app.setTextureAttributes(texAtt);
    }

    public static void SetMaterialToAppearance(Appearance app) {
        Material mat = new Material();
        mat.setAmbientColor(new Color3f(1f, 1f, 1f));
        mat.setDiffuseColor(new Color3f(1f, 1f, 1f));
        mat.setSpecularColor(new Color3f(0f, 0f, 0f));
        mat.setShininess(0);
        app.setMaterial(mat);
    }

    public static void SetMaterialToAppearance(Appearance app, Color3f ambientColor, Color3f diffuseColor,
            Color3f specularColor, float shininess) {
        Material mat = new Material();
        mat.setCapability(Material.ALLOW_COMPONENT_WRITE);
        mat.setAmbientColor(ambientColor);
        mat.setDiffuseColor(diffuseColor);
        mat.setSpecularColor(specularColor);
        mat.setShininess(shininess);
        app.setMaterial(mat);
    }

    private static Group LoadSimpleObjectFromFile(String fName, boolean reformable) {
        Scene s = null;
        ObjectFile objFile = new ObjectFile();
        try {
            s = objFile.load(fName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Group obj = s.getSceneGroup();
        Enumeration<Node> sceneChildren = obj.getAllChildren();
        while (sceneChildren.hasMoreElements()) {
            Node node = sceneChildren.nextElement();
            node.setPickable(false);
            if (node instanceof Shape3D) {
                Shape3D shape = (Shape3D) node;
                for (int j = 0; j < shape.numGeometries(); j++) {       //三角形链优化
                    Geometry geo = shape.getGeometry(j);
                    if (geo instanceof GeometryArray) {
                        GeometryInfo geoInfo=new GeometryInfo((GeometryArray)geo);
                                Stripifier st = new Stripifier();
                                st.stripify(geoInfo);
                        shape.setGeometry(geoInfo.getGeometryArray(true,false,true)); 
                    }
                }
            }
        }
        //Hashtable h= s.getNamedObjects();
        //System.out.println(h);
        fixTextureMix(obj, reformable);
        return obj;
    }

    private static void fixTextureMix(Group g, boolean reformable) {
        for (int i = 0; i < g.numChildren(); i++) {
            Node n = g.getChild(i);
            if (n instanceof Group) {
                fixTextureMix((Group) n, reformable);
            }
            if (n instanceof Shape3D) {
                Shape3D shape = (Shape3D) n;
                /*for (int j=0; j<shape.numGeometries();j++ ){
                Geometry geo=shape.getGeometry(j);
                if (geo instanceof GeometryArray && reformable){
                ((GeometryArray)geo).setCapability(GeometryArray.ALLOW_REF_DATA_READ);
                ((GeometryArray)geo).setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);
                }
                }*/
                Appearance app = shape.getAppearance();
                TextureAttributes textAtt = new TextureAttributes();
                textAtt.setTextureMode(TextureAttributes.MODULATE);
                app.setTextureAttributes(textAtt);
            }

        }
    }

    private static void printGroupInfo(Group g, String tag) {
        for (int i = 0; i < g.numChildren(); i++) {
            Node n = g.getChild(i);
            System.err.println(tag + n);
            if (n instanceof Group) {
                printGroupInfo((Group) n, "-" + tag);
            }
            if (n instanceof Shape3D) {
                Shape3D shape = (Shape3D) n;
                for (int j = 0; j < shape.numGeometries(); j++) {
                    Geometry geo = shape.getGeometry(j);
                    System.err.println(tag + "-Geometry:" + geo);
                }
                Appearance app = shape.getAppearance();
                //app.setTexture(null);
                System.err.println(tag + "-Appearance " + app);
                Material mat = app.getMaterial();
                System.err.println(tag + "-Appearance-Material " + mat);
                Texture texture = app.getTexture();
                System.err.println(tag + "-Appearance-Texture " + texture);
                TextureAttributes textAtt = new TextureAttributes();
                textAtt.setTextureMode(TextureAttributes.MODULATE);
                app.setTextureAttributes(textAtt);
            }

        }
    }
}
